<?php
require(__DIR__ . '/config.php');
error_reporting(E_ALL &~ E_NOTICE);

function db() {
  static $db = null;
  if ($db === null) {
    $db = new PDO(sprintf('mysql:host=%s;port=%s;dbname=%s', DB_HOST, DB_PORT, DB_NAME), DB_USER, DB_PWD);
  }
  return $db;
}

function redis() {
  static $redis = null;
  if ($redis === null) {
    $redis = new Redis();
    $redis->connect(REDIS_HOST, REDIS_PORT);
    $redis->select(REDIS_INDEX);
  }
  return $redis;
}

function json($data) {
  $data['success'] = isset($data['error']);
  return json_encode($data, JSON_UNESCAPED_UNICODE);
}

function isValidKey($key) {
  return preg_match('/^([a-zA-Z0-9]+)$/', $key);
}

function getByKey($key) {
  $redis = redis();
  $redis_key = "url_$key";
  if ($redis->exists($redis_key)) {
    $info = unserialize($redis_key);
    if ($info['expire'] < time()) {
      // 过期了
      db()->query("DELETE FROM `su_url` WHERE id = '{$info['id']}'");
      $redis->del($redis_key);
      return null;
    }
    return $info;
  }
  // 不存在，新查询
  $result = db()->query("SELECT * FROM `su_url` WHERE k = '$key' LIMIT 0, 1");
  if ($result->rowCount() === 0) {
    return null;
  }
  $it = $result->fetch(PDO::FETCH_ASSOC);
  // 时间转换
  if (!is_numeric($it['expire'])) {
    $it['expire'] = strtotime($it['expire']);
  }
  // 存入缓存，一小时有效
  $redis->setEx($redis_key, 3600, serialize($it));
  return $it;
}

function genKey($url) {
  $chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];

  $hash = md5($url);

  for ($i = 0; $i < 4; $i++) {
    // 把加密字符按照8位一组16进制与0x3FFFFFFF进行位与运算
    $temp = substr($hash, $i * 8, 8);
    $hex = hexdec($temp) & 0x3FFFFFFF;
    $outChars = '';
    for ($j = 0; $j < 6; $j++) {
      // 把得到的值与 0x0000003D 进行位与运算，取得字符数组 chars 索引
      $index = 0x0000003D & $hex;
      $outChars .= $chars[intval($index)];
      // 每次循环按位右移 5 位
      $hex = $hex >> 5;
    }
    // 检查这个key是否已经存在，如果不存在则返回
    if (getByKey($outChars) === null) {
      return $outChars;
    }
  }

  return null;
}